#pragma once

#include <string>

#include <utils/Concepts.h>
#include <utils/config.h>

#include <boost/describe.hpp>

namespace solar
{
#ifdef _GLIBCXX_VERSION_INCLUDED
    SOLAR_PURE_FUNCTION inline auto toMemberName(const std::string& original_name) -> std::string
    {
        return original_name + "_";
    }
#else
    SOLAR_PURE_FUNCTION constexpr auto toMemberName(const std::string& original_name) -> std::string
    {
        return original_name + "_";
    }
#endif

    template <Enum T> auto getEnumName(T t) -> std::string
    {
        bool found = false;
        std::string ret;
        boost::mp11::mp_for_each<boost::describe::describe_enumerators<std::remove_reference_t<T>>>(
            [&](auto&& D)
            {
                if (!found && D.value == t)
                {
                    found = true;
                    ret = D.name;
                }
            });
        return ret;
    }

    template <Enum T> auto getEnumValue(const std::string& t) -> T
    {
        bool found = false;
        T ret;
        boost::mp11::mp_for_each<boost::describe::describe_enumerators<std::remove_reference_t<T>>>(
            [&](auto&& D)
            {
                if (!found && D.name == t)
                {
                    found = true;
                    ret = D.value;
                }
            });
        return ret;
    }
} // namespace solar
